
#include "../../Command.h"
#include "../../User.h"

#include "../../NResource/Static.h"

#include "../../NLogic/Card.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Bag.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/VirtualCurrency.h"
#include "../../NUtil/Utils.h"
#include "../../NGameLog/Static.h"

namespace ProjectZ { namespace NCommand {

void SendFailDungeonCardReward(User * pUser, int res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(res);
	pAck->MakePacket(CMD_SC_DUNGEON_CARD_REWARD);
	pUser->Send(pAck);
}

void Command::CS_DUNGEON_CARD_REWARD(User * pUser, ::Network::Packet * pPacket)
{
/*	CS_DUNGEON_CARD_REWARD	0x081F
	{
		u8		card_type;	(0:일반, 1:젠카드)
	}

	/// 카드보상 됨 :  S -> C 모든 클라이언트에 보상정보 전송
	SC_DUNGEON_CARD_REWARD	0x0820
	{
		s16		ack;
		s8		class_type;
		u8		sheet_type;
		u16		item_tid;
		u8		item_quality;
		u8		refine_step;
		u8		eff_type0;
		u8		eff_pos0;	// 기본이펙트 : 위치
		u16		eff_value0;	// 기본이펙트 : 효과치
	}*/

	PREPARE_PACKET;

	uint8_t cardType = 0;	// 0:일반카드, 1:젠카드

	*pPacket >> cardType;

	if (cardType < 0 || cardType > 1)
	{
		DEBUGLOG("CS_DUNGEON_CARD_REWARD : cardType < 0 || cardType > 1!! cardType=%d", cardType);
		return;
	}

	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("WARNING: CN_DUNGEON_CARD_REWARD GID %d, pSpace is NULL", pUser->GetUserSeq());
		return;
	}

	if (false == pSpace->IsDungeon())
	{
		DEBUGLOG("CS_DUNGEON_CARD_REWARD : space is not single or party dungeion");
		return;
	}

	int vcIndex = static_cast<int>(EM_VCINDEX_ZEN_CARD_GACHYA);

	// 젠 카드 가격 체크
	if (1 == cardType)
	{
		if (true == NResource::Static::InstancePtr()->GetEventTime()->IsDungeonRewardZenCardEvent(pUser))
			vcIndex = static_cast<int>(EM_VCINDEX_ZEN_CARD_GACHYA_EVENT);

		NResource::VCResource::Flyweight * pFly = NResource::Static::InstancePtr()->GetVCRef()->GetFly(vcIndex);

		if (NULL == pFly)
		{
			DEBUGLOG("CS_DUNGEON_CARD_REWARD : pFly is NULL!");
			return;
		}

		if (static_cast<int>(pUser->GetVirtualCurrency()->GetZen()) < (pFly->_VC_PRICE * -1))
		{
			SendFailDungeonCardReward(pUser, ACK_NOT_ENOUGH_ZEN);
			return;
		}
	}

	NLogic::Card * pCard = pUser->GetCard();
	if (NULL == pCard)
	{
		DEBUGLOG("%s : pCard is NULL!!", __FUNCTION__);
		return;
	}

	// 이미 보상을 받았는데, 클라이언트에서 다시 패킷을 보내는 경우 예외처리
	if (1 == cardType)
	{
		if (true == pCard->GetDungeonRewardFlagZEN())
		{
			DEBUGLOG("CS_DUNGEON_CARD_REWARD : Already Receive ZEN Card Reward!!!");
			return;
		}
	}
	else
	{
		if (true == pCard->GetDungeonRewardFlag())
		{
			DEBUGLOG("CS_DUNGEON_CARD_REWARD : Already Receive NORMAL Card Reward!!!");
			return;
		}
	}

	int gachyaType = 0;

	switch (cardType)
	{
	case 0 : gachyaType = static_cast<int>(EM_1_QUALITY_GACHYA); break;
	case 1 : gachyaType = static_cast<int>(EM_3_QUALITY_GACHYA); break;
	}

	int cardIndex = NResource::Static::InstancePtr()->GetDungeonReward()->GetItemQualityIndex(pUser, gachyaType);

	if (-1 == cardIndex)
	{
		DEBUGLOG("CS_DUNGEON_CARD_REWARD : cardIndex == -1");
		return;
	}

	NLogic::Card::Data * pData = NULL;

	if (1 == cardType)
	{
		pData = pCard->GetZenCardData(static_cast<NLogic::Card::CardItemType>(cardIndex));
		pCard->SetDungeonRewardFlagZEN(true);
	}
	else
	{
		pData = pCard->GetNormalCardData(static_cast<NLogic::Card::CardItemType>(cardIndex));
		pCard->SetDungeonRewardFlag(true);
	}

	if (NULL == pData)
	{
		DEBUGLOG("CS_DUNGEON_CARD_REWARD : pData is NULL!");
		return;
	}

	NLogic::Item::Data clsData;
	clsData.tid				= pData->tid;
	clsData.sub_type		= pData->sheetType;
	clsData.class_type		= pData->classType;
	clsData.quality			= pData->quality;
	clsData.cur_refine_step	= pData->refine;
	clsData.eff_pos[0]		= pData->effPos;
	clsData.eff_type[0]		= pData->effType;
	clsData.eff_value[0]	= pData->effValue;
	clsData.quantity		= 1;
	clsData.bag_type		= NResource::Static::InstancePtr()->GetItemResource()->GetItemBagType(clsData);

	// 던전 보상 아이템은 무조건 식별아이템이 나와야 하므로,
	// 아이템의 정보를 셋팅할때 Flag값으로 사용하기 위해 일단 -99로 설정한다
	clsData.non_identity	= -99;

	// 제련 단계에 따라 기본 능력치 향상
	if (0 < clsData.cur_refine_step)
	{
		NResource::BalanceData * pBalance = NResource::Static::InstancePtr()->GetBalance()->GetBalancePtr(pUser);
		if (NULL == pBalance)
		{
			DEBUGLOG("CS_DUNGEON_CARD_REWARD : pBalance is NULL!");
			return;
		}

		for (int i = 0; i < clsData.cur_refine_step; i++)
		{
			int newValue = NUtil::AddPercentage(clsData.eff_value[0], pBalance->GetValue(EM_REFINE_STATS_ENHANCE_RATE));

			if (newValue == clsData.eff_value[0])
			{
				clsData.eff_value[0] += 1;
			}
			else
			{
				clsData.eff_value[0] = newValue;
			}
		}
	}

	NLogic::Bag * pBag = pUser->GetBag(static_cast<INVEN_BAG_TYPE>(clsData.bag_type));
	if (NULL == pBag)
	{
		DEBUGLOG("CS_DUNGEON_CARD_REWARD : pBag is NULL! bagtype=%d", clsData.bag_type);
		return;
	}

	int ackReturn = ACK_OK;
	bool bBagFull = false;

	// 아이템 정보 저장
	NLogic::Item * pItem = pBag->AddItemWithData(clsData, bBagFull);

	// 아이템 저장 실패
	if (NULL == pItem)
	{
		// 인벤토리가 꽉 찬 경우 메일로 발송
		if (true == bBagFull)
		{
			ackReturn = ACK_INVEN_FULL_SEND_MAIL;

			NLogic::MailBox::Mail::Data clsMailData;

			clsMailData.send_user_seq		= 0;
			clsMailData.send_user_nickname	= "GAMEVIL";
			clsMailData.recv_user_seq		= pUser->GetUserSeq();
			clsMailData.gift_status			= EM_GIFT_ITEM;
			clsMailData.item				= clsData;
			clsMailData.message				= NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessageDungeonReward(cardType);

			// 아이템 부가 정보 세팅
			NResource::Static::InstancePtr()->GetItemResource()->SetItemDataFromResource(pUser, clsMailData.item);

			// 던전 보상 아이템은 무조건 미식별
			clsMailData.item.non_identity = 0;

			if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
			{
				DEBUGLOG("CS_DUNGEON_CARD_REWARD : false == NLogic::NFunction::SendMail(pUser, clsMailData)");
				return;
			}
		}
		else
		{
			DEBUGLOG("CS_DUNGEON_CARD_REWARD : NULL == pBag->AddItemWithData(clsData)");
			return;
		}
	}


	::ProjectZ::NGameLog::Bson * pBson = ::ProjectZ::NGameLog::Static::Instance().GETBSONPOOL()->NEW();
	if(NULL != pBson)
	{
		pBson->SetCollections("log_dungeon_play");
		bson * bson = pBson->GetBsonData();
		bson_append_int( bson, "user_seq", pUser->GetUserSeq() );
		bson_append_int( bson, "company", pUser->GetCompany() );
		bson_append_int( bson, "sale_code", pUser->GetSaleCode() );
		bson_append_int( bson, "character_class", pUser->GetCharacterInfo().classtype );
		bson_append_int( bson, "character_level", pUser->GetCharacterInfo().level );
		bson_append_int( bson, "space_num", pSpace->GetData()._index );
		bson_append_int( bson, "start_time", pSpace->GetData()._starttick );
		bson_append_int( bson, "end_time", pSpace->GetData()._finishtick );
		bson_append_int( bson, "play_time", pSpace->GetData()._finishtick - pSpace->GetData()._starttick );
		bson_append_int( bson, "dungeon_type", static_cast<int>(pSpace->GetData()._spaceType) );
		bson_append_int( bson, "dungeon_tid", pSpace->GetData()._table_id );
		bson_append_int( bson, "dungeon_mod", pSpace->GetData()._difficulty );
		bson_append_int( bson, "exp", pUser->GetBattle()->GetData().hunting_exp );
		bson_append_int( bson, "gold", pUser->GetBattle()->GetData().get_gold );
		if (NULL != pItem)
			bson_append_int( bson, "item_seq", pItem->GetItemSeq() );
		else
			bson_append_int( bson, "item_seq", 0 );
		bson_append_time_t( bson, "reg_time", time(NULL) );

		::ProjectZ::NGameLog::MongoDB * pMongoDB = ::ProjectZ::NGameLog::Static::Instance().GetMongoDB();
		pMongoDB->Push(pBson);
	}


	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ackReturn);
	*pAck << static_cast<int8_t>(clsData.class_type);
	*pAck << static_cast<uint8_t>(clsData.sub_type);
	*pAck << static_cast<uint16_t>(clsData.tid);
	*pAck << static_cast<uint8_t>(clsData.quality);
	*pAck << static_cast<uint8_t>(clsData.cur_refine_step);
	*pAck << static_cast<uint8_t>(clsData.eff_type[0]);
	*pAck << static_cast<uint8_t>(clsData.eff_pos[0]);
	*pAck << static_cast<uint16_t>(clsData.eff_value[0]);
	pAck->MakePacket(CMD_SC_DUNGEON_CARD_REWARD);
	pUser->Send(pAck);

	// VC 처리
	if (1 == cardType)
	{
		NLogic::NFunction::VCProcess(pUser, vcIndex);
	}
}

} /*NCommand*/ } /*ProjectZ*/
